#include <stdio.h>
#include "RaptorOld.h"

#if 1
#define msg(a) printf a
#else
#define msg(a)
#endif



enum KeyCode {VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_SPACE, VK_ENTER, VK_ESC};

enum Color{
	clBlack = 0,
			clBlue,
			clGreen,
			clCyan,
			clRed,
			clMagenta,
			clYellow,
			clWhite
};

enum Sound{
	sRaptor,
	sHelicopter,
	sMig,
	sMissile,
	sExplosion,
	sAid,
	sGameOver,
	sRaptorHit
};

enum ObjectType{
	otRaptor = 0,
			otHelicopter,
			otMig,
			otMissile,
			otExplosion,
			otBullet,
			otAid
};

enum Direction{
	dirUp,
	dirDown,
	dirHanging
};

enum ShootPosition{
	spLeft,
	spRight,
	spCenter
};

typedef struct {
	int msStamp; // millisecond
	int tsCount; // thirty second count
	int interval; // ms for next event
} timeStamp;

typedef struct {
	int objId;	// Object id (indicates what address object
	// is saved to)
	int x;	// sprites x position (left to right)
	int y; // sprites y position (top to bottom)

	enum Color color; // sprites colour
	enum ObjectType type; // type of sprite
	int enabled; 	// if object is enabled.
	int destroyed; // =1 when object is destroyed
	// To disable graphics, x and y must be
	// outside of screen area.
	// Therefore this value must be disabled by setObjEnabled,
	// so that x and y is set outside of screen area when
	// disabled.

	int isEnemy;	// enemy=1 for enemy objects (for collision detection)

	// indicates that object has been changed,
	// so that we don't save unchanged data.
	int positionHasChanged;
	int idHasChanged;

	int collisionInspect; // only check for collision if value > 0
	int collisionImpact; // damage made to colliding object
	int maxhealth; // used for raptor
	int health; // health of object. When health is 0 or less, object is destroyed
	int pointsForDestroy; // points earned for destroying object

	// time (ms) last time object was moved (for speed)
	timeStamp moveTime;
	timeStamp shotTime;
	int isHomingMissile; // only used for enemy missiles

	enum Direction direction;
	enum ShootPosition shootPosition; // only Raptor uses this at the moment

} baseObj;



void initialize();

void getObjAddressOffset(enum ObjectType type, int* start, int* end);
void getTypeImgSize(enum ObjectType type, int* width, int* height);

baseObj* createRaptor();
void raptorShoot(baseObj* obj);
baseObj* createBaseObj(int id, int x,int y, enum Color color, enum ObjectType type, int isEnemy);
void setObjX(int value, baseObj* obj);
void setObjY(int value, baseObj* obj);
void setObjEnabled(int value, baseObj* obj);
void saveBaseObj(baseObj* obj);
int getObjVGAID(baseObj* obj);
void moveRaptor();
void moveObjects();
void moveObject(baseObj* obj);
int keyPressed(enum KeyCode key);

void clearEnabledObjects();
int getNewObjectId(enum ObjectType type);

void collisionDetection();
void collisionCheck(int obj1Start, int obj1End, int obj2Start, int obj2End);
int collision(baseObj* a, baseObj* b);
int getCollisionRadius(baseObj* obj);
void damageControl(baseObj* obj, int doBlowUp);
void blowUp(baseObj* obj, int destroy);

void setGameOver();
void setScore(int Value);
void addToScore(int Value);
void displayScore();
void displayHealth();
void playSound(enum Sound sound);

int min(int v1, int v2);
int max(int v1, int v2);


// global variables
unsigned int* IO = (unsigned int*)IO_BASE;
int score = 0;
int gameOver = 0;

timeStamp collisionTestTime;
timeStamp test;
timeStamp test2;
timeStamp test3;
timeStamp test4;
timeStamp test5;

// arrays storing baseobjects & relevant info
int enabledObjects[OBJECT_COUNT];
baseObj baseObjects[OBJECT_COUNT];


void getObjAddressOffset(enum ObjectType type, int* start, int* end){
	switch(type){
	case(otRaptor):
		*start=RAPTOR_ADDR;
		*end=RAPTOR_ADDR;
		break;
	case(otHelicopter):
		*start=HELICOPTER_ADDR_START;
		*end=HELICOPTER_ADDR_END;
		break;
	case(otMig):
		*start=MIG_ADDR_START;
		*end=MIG_ADDR_END;
		break;
	case(otMissile):
		*start=MISSILE_ADDR_START;
		*end=MISSILE_ADDR_END;
		break;
	case(otExplosion):
		*start=EXPLOSION_ADDR_START;
		*end=EXPLOSION_ADDR_END;
		break;
	case(otBullet):
		*start=BULLET_ADDR_START;
		*end=BULLET_ADDR_END;
	break;
	case(otAid):
		*start=AID_ADDR_START;
	*end=AID_ADDR_END;
	break;
	default:;
	}
}

void getTypeImgSize(enum ObjectType type, int* width, int* height){
	switch(type){
	case(otRaptor):
		*width=RAPTOR_IMG_WIDTH;
		*height=RAPTOR_IMG_HEIGHT;
		break;
	case(otHelicopter):
		*width=HELICOPTER_IMG_WIDTH;
		*height=HELICOPTER_IMG_HEIGHT;
		break;
	case(otMig):
		*width=MIG_IMG_WIDTH;
		*height=MIG_IMG_HEIGHT;
		break;
	case(otMissile):
		*width=MISSILE_IMG_WIDTH;
		*height=MISSILE_IMG_HEIGHT;
		break;
	case(otExplosion):
		*width=EXPLOSION_IMG_WIDTH;
		*height=EXPLOSION_IMG_HEIGHT;
		break;
	case(otBullet):
		*width=BULLET_IMG_WIDTH;
		*height=BULLET_IMG_HEIGHT;
		break;
	case(otAid):
		*width=AID_IMG_WIDTH;
		*height=AID_IMG_HEIGHT;
		break;
	default:;
	}
}

baseObj* createRaptor(){
	baseObj* o = createBaseObj(RAPTOR_ADDR,350,480,clWhite,otRaptor,0);

	o->maxhealth = 8;
	o->health = o->maxhealth; // max for raptor
	o->collisionImpact = 1000; // everything gets destroyed when colliding with raptor
	o->moveTime.interval = 25;
	o->shotTime.interval = 150;
	//o.moveInterval = 25;
	//o.shootInterval = 150;
	o->shootPosition = spRight;

	playSound(sRaptor);

	//enabledObjects[RAPTOR_ADDR]=1;
	//baseObjects[RAPTOR_ADDR]=o;
	return o;
}

baseObj* createHelicopter(int x, int y){
	int id;
	baseObj* o = 0;
	id = getNewObjectId(otHelicopter);
	if (id>=0){//!enabledObjects[id]){

		//if (id>-1){
		o = createBaseObj(id,x,y,clGreen,otHelicopter,1);
		o->health = 2;
		o->collisionImpact = 1;
		o->direction = dirDown;
		o->moveTime.interval = 20;

		playSound(sHelicopter);
		//o.moveInterval = 25;
		//o.shootInterval = 500;
		//enabledObjects[o.objId]=1;
		//baseObjects[o.objId]=o;
	}
	return o;
}

baseObj* createMig(int x, int y){
	int id;
	baseObj* o = 0;
	id = getNewObjectId(otMig);
	if (id>=0){//!enabledObjects[id]){

		//if (id>-1){
		o = createBaseObj(id,x,y,clBlue,otMig,1);
		o->health = 1;
		o->collisionImpact = 1;
		o->direction = dirDown;
		o->moveTime.interval = 15;

		playSound(sMig);
		//o.moveInterval = 25;
		//o.shootInterval = 500;
		//enabledObjects[o.objId]=1;
		//baseObjects[o.objId]=o;
	}
	return o;
}

baseObj* createBullet(int x, int y){
	int id;
	baseObj* o = 0;
	id = getNewObjectId(otBullet);
	if (id>=0){//!enabledObjects[id]){

		//if (id>-1){
		o = createBaseObj(id,x,y,clYellow,otBullet,1);
		o->health = 1;
		o->collisionImpact = 1;
		o->direction = dirDown;
		o->moveTime.interval = 70;
		//o.moveInterval = 25;
		//o.shootInterval = 500;
		//enabledObjects[o.objId]=1;
		//baseObjects[o.objId]=o;
	}
	return o;
}

baseObj* createAid(int x, int y){
	int id;
	baseObj* o = 0;
	id = getNewObjectId(otAid);
	if (id>=0){//!enabledObjects[id]){
		//if (id>-1){
		o = createBaseObj(id,x,y,clMagenta,otAid,1);
		o->health = 1;
		o->collisionImpact = -2;
		o->direction = dirDown;
		o->moveTime.interval = 70;
	}
	return o;
}

baseObj* createExplosion(int xCenter, int yCenter, int isHit){
	int id, x, y;
	baseObj* o = 0;
	id = getNewObjectId(otExplosion);
	if (id>0){
		x = xCenter-(EXPLOSION_IMG_WIDTH/2);
		y = yCenter-(EXPLOSION_IMG_HEIGHT/2);

		o = createBaseObj(id,x,y,clRed,otExplosion,0);
		o->collisionInspect = 0;
		o->destroyed = 1;
		o->direction = dirHanging;
		o->moveTime.msStamp = IO[IO_MSTIMER_D];
		o->moveTime.tsCount = IO[IO_TSTIMER_D];
		o->moveTime.interval = 750;
	}

	if(isHit){
		playSound(sRaptorHit);
	} else{
		playSound(sExplosion); // play sound even if no explosion is displayed
	}
	return o;
}

//int wait(int* lastTime, int* lastTSCount, int interval){
int wait(timeStamp* stamp){
int time = IO[IO_MSTIMER_D];
	int ts_count = IO[IO_TSTIMER_D]; // thirty second counter
	int retVal = 0;
	int max_ms = 30000;
	int nextTime;
	int hasOccurred = 0;

	if((stamp->tsCount)==ts_count){
		if(stamp->msStamp+stamp->interval<time){
			hasOccurred = 1;
		}
	} else if ((ts_count-stamp->tsCount)==1){
		if(stamp->interval-(max_ms-stamp->msStamp)<time){
			hasOccurred = 1;
		}
	} else if (ts_count-stamp->tsCount>1){
		hasOccurred = 1;
	}

	if(hasOccurred){
		stamp->msStamp = time;
		stamp->tsCount = ts_count;
		retVal = 1;
	}
	return retVal;
}

void raptorShoot(baseObj* obj){
	int time = IO[IO_MSTIMER_D];
	int h;
	// i=-1 if no missile can be assigned
	int i = getNewObjectId(otMissile);
	int xOffset;
	baseObj* missile;

	if((i>-1) && wait(&obj->shotTime)){
	//if((i>-1) && wait(&obj->lastShotTime,&obj->lastShotTSCount,obj->shootInterval)){
		if (obj->shootPosition==spRight){
			xOffset = 36;
			obj->shootPosition=spLeft;
		} else{
			xOffset = 2;
			obj->shootPosition=spRight;
		}
		missile = createBaseObj(i,obj->x+xOffset,obj->y+40,clRed,otMissile,0);
		missile->health = 1;
		missile->collisionImpact = 2;
		missile->direction = dirUp;
		missile->moveTime.interval = 18;

		playSound(sMissile);
		//missile.moveInterval=18;
		//enabledObjects[i] = 1;
		//baseObjects[i]=missile;
	}
}

baseObj* createBaseObj(int id, int x,int y, enum Color color, enum ObjectType type, int isEnemy){
	baseObj b;

	b.objId = id;
	b.x = x;
	b.y = y;
	b.color = color;
	b.type = type;

	b.isEnemy = isEnemy;
	b.enabled = 1;
	b.destroyed = 0;

	b.idHasChanged = 1;
	b.positionHasChanged = 1;
	saveBaseObj(&b);

	b.shotTime.msStamp = IO[IO_MSTIMER_D];
	b.shotTime.tsCount = IO[IO_TSTIMER_D];
	b.moveTime.msStamp = IO[IO_MSTIMER_D];
	b.moveTime.tsCount = IO[IO_TSTIMER_D];
/*
	b.lastShotTime = IO[IO_MSTIMER_D];
	b.lastShotTSCount = IO[IO_TSTIMER_D];
	b.lastMovedTime = IO[IO_MSTIMER_D];
	b.lastMovedTSCount = IO[IO_TSTIMER_D];
*/
	b.collisionInspect = 1;
	b.collisionImpact = 0;

	enabledObjects[b.objId]=1;
	baseObjects[b.objId]=b;

	return getBaseObj(b.objId);
}

void setObjX(int value, baseObj* obj){
	if (value!=obj->x){
		obj->x = value;
		obj->positionHasChanged = 1;
	}
}

void setObjY(int value, baseObj* obj){
	if (value!=obj->y){
		obj->y = value;
		obj->positionHasChanged = 1;
	}
}

// For enabling/disabling baseObj
void setObjEnabled(int value, baseObj* obj){
	obj->enabled = value;
	// if object is disabled, move outside of
	// screen area, so that it is not painted.
	if (!value){
		enabledObjects[obj->objId] = 0;
		setObjX(0,obj);
		setObjY(0,obj);
		saveBaseObj(obj);
	}
}

void saveBaseObj(baseObj* obj){
	if (obj->idHasChanged){
		IO[VGA_ID+obj->objId]=getObjVGAID(obj);
	}
	if (obj->positionHasChanged){
		IO[VGA_X+obj->objId]=obj->x;
		IO[VGA_Y+obj->objId]=obj->y;
	}
	obj->positionHasChanged = 0;
	obj->idHasChanged = 0;
}


// gets ID for VGA controller.
// Return value is (hex) 0x00CT,
// where C is color and T is Type.
int getObjVGAID(baseObj* obj){
	int val = obj->color;//*16+obj->type;
	return val;
}


void moveRaptor(){
	//int time = IO[IO_MSTIMER_D];
	baseObj* obj = getBaseObj(RAPTOR_ADDR);
	int x = obj->x;
	int y = obj->y;
	int borderVal = 0;

	if(wait(&obj->moveTime)){
	//if(wait(&obj->lastMovedTime,&obj->lastMovedTSCount,obj->moveInterval)){
	//if ((obj->lastMovedTime+obj->moveInterval)<time){
	//	obj->lastMovedTime = time;
		if (keyPressed(VK_UP)){
			y = y-10;
			if(y<SCREEN_TOP){
				y = SCREEN_TOP;
			}
		}
		if (keyPressed(VK_DOWN)){
			y = y+10;
			borderVal = SCREEN_BOTTOM-IMAGE_WIDTH;
			if (y>borderVal){//(SCREEN_BOTTOM-IMAGE_WIDTH)){
				y = borderVal;
			}
		}
		if (keyPressed(VK_RIGHT)){
			x = x+10;
			borderVal = SCREEN_RIGHT-IMAGE_WIDTH;
			if(x>borderVal){
				x = borderVal;
			}
		}
		if (keyPressed(VK_LEFT)){
			x = x-10;
			if(x<SCREEN_LEFT){
				x = SCREEN_LEFT;
			}
		}
		if (keyPressed(VK_SPACE)){
			raptorShoot(obj);
		}

		if (keyPressed(VK_ENTER)){
			//createHelicopter(x,10);
		}

		setObjX(x,obj);
		setObjY(y,obj);
		saveBaseObj(obj);
	}
}

void moveObjects(){
	int i;
	// don't move raptor (RAPTOR_ADDR)
	for (i=OBJECT_COUNT-1; i>-1; i--){
		if (i!=RAPTOR_ADDR){
			if(enabledObjects[i]){
				moveObject(getBaseObj(i));
				//moveObject(&baseObjects[i]);
			}
		}
	}
}

void moveObject(baseObj* obj){
	int y = obj->y;

	int outOfBoundsUp;
	int outOfBoundsDown;

	//int time = IO[IO_MSTIMER_D];

	outOfBoundsUp = SCREEN_TOP-IMAGE_HEIGHT;
	outOfBoundsDown = SCREEN_BOTTOM;
	if (wait(&obj->moveTime)){
	//if ((!(obj->direction==dirHanging))&&(wait(&obj->lastMovedTime,&obj->lastMovedTSCount,obj->moveInterval))){
	//if ((!(obj->direction==dirHanging))&&(obj->lastMovedTime+obj->moveInterval)<time){
	//	obj->lastMovedTime = time;

		if (obj->destroyed){
			setObjEnabled(0,obj);
		}

		if (obj->type==otHelicopter){
			y = y+3;
		} else{


		if (obj->direction==dirUp){
			y = y-10;
		} else if (obj->direction==dirDown){
			y = y+10;
		} else{
			y = y+0;
		}
		}

		//setObjX(x,obj);
		setObjY(y,obj);
		saveBaseObj(obj);

		if ((obj->direction==dirUp && y<outOfBoundsUp) ||
		    (obj->direction==dirDown && y>outOfBoundsDown))
		{
			setObjEnabled(0,obj);
		}
		/*
		if (((obj->direction=dirUp) && (y<SCREEN_TOP))||
			((obj->direction=dirDown && y>SCREEN_BOTTOM))){
			setObjEnabled(0,obj);
		}*/
	}
}

// returns 1 if key is down
int keyPressed(enum KeyCode key){
	int keyboard = IO[IO_PS2KBD_D];

	int val;
	switch(key){
	case VK_UP: val = 0x0001u; break;
	case VK_RIGHT: val = 0x0002u; break;
	case VK_LEFT: val = 0x0004u; break;
	case VK_DOWN: val = 0x0008u; break;
	case VK_SPACE: val = 0x0010u; break;
	case VK_ENTER: val = 0x0020u; break;
	case VK_ESC: val = 0x0040u; break;
	default: val = 0;
	}

	return keyboard&val;
}

void clearEnabledObjects(){
	int i=0;
	for(i=0; i<OBJECT_COUNT; i++){
		enabledObjects[i]=0;

		IO[VGA_ID+i] = 0;
		IO[VGA_X+i] = 0;
		IO[VGA_Y+1] = 0;
	}
}

// gets largest available id for object
// if no objects are available, then function returns -1
int getNewObjectId(enum ObjectType type){
	int i;
	int retVal = -1;
	int start, end;
	getObjAddressOffset(type,&start,&end);
	for(i=start;i>=end;i--){
		if (!enabledObjects[i]){
			retVal = i;
			break;
		}
	}
	return retVal;
}

void collisionDetection(){
	if(wait(&collisionTestTime)){
		collisionCheck(RAPTOR_ADDR, RAPTOR_ADDR, HELICOPTER_ADDR_START, MIG_ADDR_END);
		collisionCheck(RAPTOR_ADDR, RAPTOR_ADDR, AID_ADDR_START, AID_ADDR_END);
		collisionCheck(RAPTOR_ADDR, RAPTOR_ADDR, BULLET_ADDR_START, BULLET_ADDR_END);
		collisionCheck(HELICOPTER_ADDR_START, MIG_ADDR_END, MISSILE_ADDR_START, MISSILE_ADDR_END);

		displayHealth();
	}
}

void collisionCheck(int obj1Start, int obj1End, int obj2Start, int obj2End){
	int i,j;
	baseObj* obj1;
	baseObj* obj2;

	for(i=obj1Start;i>=obj1End;i--){
		obj1 = getBaseObj(i);
		if (enabledObjects[i] && obj1->collisionInspect){
			for(j=obj2Start;j>=obj2End;j--){
				obj2 = getBaseObj(j);
				if (enabledObjects[j] && obj2->collisionInspect){
					if (obj2->isEnemy!=obj1->isEnemy){
						if (collision(obj1,obj2)){
							obj1->health=min(obj1->maxhealth,(obj1->health-obj2->collisionImpact));
							obj2->health=min(obj2->maxhealth,(obj2->health-obj1->collisionImpact));
							damageControl(obj1, obj2->type!=otAid);
							damageControl(obj2, obj1->type!=otAid);
							if ((obj1->type==otAid)|| (obj2->type==otAid)){
								playSound(sAid);
							}
						}

					}
				}
			}
		}
	}
}

int collision(baseObj* a, baseObj* b){
	int x1,x2,y1,y2,r;
	int colRa, colRb, colR;
	int squareDistX, squareDistY;
	int img1Height, img2Height;
	int img1Width, img2Width;
	int minHeight, minWidth;

	getTypeImgSize(a->type, &img1Width, &img1Height);
	getTypeImgSize(b->type, &img2Width, &img2Height);

	minWidth = max(img1Width, img2Width);
	minHeight = max(img1Height, img2Height);

	if(a->enabled && b->enabled){
		squareDistX = (a->x-b->x);
		if (squareDistX<0){
			squareDistX = squareDistX*(-1);
		}
		squareDistY = (a->y-b->y);
		if (squareDistY<0){
			squareDistY = squareDistY*(-1);
		}
		if((squareDistX<minWidth) && (squareDistY<minHeight)){
			// calculate coordinates for centrum of the circels that defines the objects
			x1 = a->x + (img1Width/2);
			y1 = a->y + (img1Height/2);
			x2 = b->x + (img2Width/2);
			y2 = b->y + (img2Height/2);

			// calculate radius
			r = ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); // cirklens ligning (x-a)^2 + (y-b)^2 = r^2
			colRa = getCollisionRadius(a);
			colRb = getCollisionRadius(b);
			colR = (colRa+colRb);
			if(r < (colR*colR)){
				return 1; // they are colliding
			}
		}
	}
	return 0; // they are NOT colliding
}

int min(int v1, int v2){
	int val;
	if(v1<v2){
		val = v1;
	} else{
		val = v2;
	}
	return val;
}

int max(int v1, int v2){
	int val;
	if(v1>v2){
		val = v1;
	} else{
		val = v2;
	}
	return val;
}

int getCollisionRadius(baseObj* obj){
	// to do: radius corresponding to type
	int val;

	switch(obj->type){
	case otRaptor: val = 22; break;
	case otHelicopter: val = 22; break;
	case otMig: val = 20; break;
	case otMissile: val = 3; break;
	case otBullet: val = 2; break;
	case otAid: val = 16; break;
	default: val = 0; // no collision
	}

	return val;
}

void damageControl(baseObj* obj, int doBlowUp){
	// destroy obj if health is less than or equal to 0
	if (doBlowUp){
		if (obj->health<=0){
			// points if enemy is destroyed (even if by colliding into it)
			if (obj->isEnemy){
				addToScore(obj->pointsForDestroy);
			}

			switch(obj->type){
			case otHelicopter:
			case otMig: blowUp(obj,1); break;
			case otRaptor: blowUp(obj, 1); setGameOver(); break;
			default: setObjEnabled(0,obj);
			}
		} else{
			if(obj->type==otRaptor){
				blowUp(obj,0); // don't destroy
			}
		}
	}

}

void setGameOver(){
	gameOver=1;
	playSound(sGameOver);
}

void blowUp(baseObj* obj, int destroy){
	int x,y,width,height;
	int yOffset;

	if (destroy){
		obj->destroyed = 1;
		obj->collisionInspect = 0;
		obj->direction = dirHanging;
		obj->moveTime.msStamp = IO[IO_MSTIMER_D];
		obj->moveTime.tsCount = IO[IO_TSTIMER_D];
		obj->moveTime.interval=500;
	}
	getTypeImgSize(obj->type, &width, &height);
	x = obj->x + (width/2);
	if (obj->type==otRaptor){
		yOffset = 0;
	} else{
		yOffset = 15; // below center
	}
	y = (obj->y + (height/2))+yOffset; // just below center
	createExplosion(x,y, !destroy);
	// should blow up, but for now we just disable
	//setObjEnabled(0,obj);
}

void setScore(int Value){
	score = Value;
	displayScore();
}

void addToScore(int Value){
	score = score+Value;
	displayScore();
}

void displayScore(){
	IO[IO_SSEG_D] = score;
}

void playSound(enum Sound sound){
	switch(sound){
		case(sRaptor): printf("1"); break;
		case(sHelicopter): printf("2"); break;
		case(sMig): printf("3"); break;
		case(sMissile): printf("4"); break;
		case(sExplosion): printf("5"); break;
		case(sAid): printf("6"); break;
		case(sGameOver): printf("7"); break;
		case(sRaptorHit): printf("8"); break;
		default:;
	}
}

void displayHealth(){
	int h=0;
	baseObj* o;
	//unsigned int display;

	if (enabledObjects[RAPTOR_ADDR]){
		o = getBaseObj(RAPTOR_ADDR);
		h = o->health;
	}

	//IO[IO_LED_D] = h;

	switch(h){
	case(1): IO[IO_LED_D] = 0x0001u; break;
	case(2): IO[IO_LED_D] = 0x0003u; break;
	case(3): IO[IO_LED_D] = 0x0007u; break;
	case(4): IO[IO_LED_D] = 0x000Fu; break;
	case(5): IO[IO_LED_D] = 0x001Fu; break;
	case(6): IO[IO_LED_D] = 0x003Fu; break;
	case(7): IO[IO_LED_D] = 0x007Fu; break;
	case(8): IO[IO_LED_D] = 0x00FFu; break;
	default: IO[IO_LED_D] = 0;
	}
}


int main(){
	int x,y, x2, x3,x4,x5;
	int startGame;
//	baseObj* obj;

	while (1){
		startGame = 1;



		test.interval = 600;
		test.msStamp = IO[IO_MSTIMER_D];
		test.tsCount = IO[IO_TSTIMER_D];

		test2.interval = 450;
		test2.msStamp = IO[IO_MSTIMER_D];
		test2.tsCount = IO[IO_TSTIMER_D];
		test3.interval = 20;
		test3.msStamp = IO[IO_MSTIMER_D];
		test3.tsCount = IO[IO_TSTIMER_D];

		test4.interval = 700;
		test4.msStamp = IO[IO_MSTIMER_D];
		test4.tsCount = IO[IO_TSTIMER_D];

		test5.interval = 1000;
		test5.msStamp = IO[IO_MSTIMER_D];
		test5.tsCount = IO[IO_TSTIMER_D];

		x = 70;
		y = 10;
		x2 = 700;
		x3 = 70;
		x4 = 300;
		x5 = 300;

		//createRaptor();

		//obj = getBaseObj(RAPTOR_ADDR);

		//baseObj obj2 = createBaseObj(0,170,200,clGreen,otHelicopter,1);
		//baseObj obj3 = createBaseObj(1,240,200,clBlue,otMig,1);
		//baseObj obj4 = createBaseObj(2,310,200,clYellow,otBullet,1);
		//baseObj obj5 = createBaseObj(3,380,200,clRed,otMissile,1);

		while(!keyPressed(VK_ESC)){
			if(startGame){
				startGame=0;
				// initialize
				initialize();
			}

			if(!gameOver){
				moveRaptor();
				moveObjects();
				collisionDetection();
				displayHealth();


				if(wait(&test)){
					createHelicopter(x,y);
					x = x+64;
					if(x>700){ x=70; }
				}
				if(wait(&test2)){
					createMig(x2,y);
					x2 = x2-50;
					if(x2<64){ x2=700; }
				}
				if(wait(&test5)){
					createAid(x5,y);
					createBullet(x5+100,y);
				}

			}



/*			if(wait(&test3)){
				createBullet(x3,y);
				x3 = x3+5;
				if(x3>700){x3=70;}
			}
			if(wait(&test4)){
				createBullet(x4,y);
				x4 = x4+5;
				if(x4>700){x4=70;}
			}
*/

		}
	}

	return 1;

}


void initialize(){
	clearEnabledObjects();

	gameOver = 0;
	collisionTestTime.msStamp = IO[IO_MSTIMER_D];
	collisionTestTime.tsCount = IO[IO_TSTIMER_D];
	collisionTestTime.interval = COLLISIONTEST_INTERVAL;

	setScore(0);
	createRaptor();
}
